home *** CD-ROM | disk | FTP | other *** search
/ Tricks of the Mac Game Programming Gurus / TricksOfTheMacGameProgrammingGurus.iso / Book Chapters / 02 - Basic Game Graphics / HSV Demo 2 ƒ / HSV Demo2.c < prev   
C/C++ Source or Header  |  1995-03-30  |  9KB  |  311 lines

  1. //\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/
  2. //
  3. //    HSV Demo 2.c
  4. //
  5. //    Demonstrates drawing with HSV colors and building a CLUT
  6. //    from scratch. Nicer colors than HSV Demo 1 because we're
  7. //    customizing our color environment with our spiffy clut.
  8. //    HSV Demo 1 used a nice but insufficient CLUT provided by
  9. //    the System.
  10. //
  11. //    Also shows how to use the Process Manager to obtain the
  12. //    name of the application.
  13. //
  14. //    History:
  15. //
  16. //    950225 jb: Written
  17. //    950305 jb: Cleaned up and commented
  18. //
  19. //\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/
  20.  
  21.  
  22. //  __#Defines________________________________________________________________________
  23. #define kMainWindowResID            1000
  24. #define kAppColorTableResID        72                    //ID of nice, 256-color palette provided by System
  25. #define    kSleepTicks                        0xFFFFFFFF    //relinquish all time; don't want null events
  26.  
  27. //  __#Headers________________________________________________________________________
  28. #include <Palettes.h>
  29. #include <math.h>
  30. #include "Utils.h"        //for EnviroCheck
  31.  
  32. //  __#Protos_________________________________________________________________________
  33. //  __ Macros_________________________________________________________________________
  34. //  __ Enums__________________________________________________________________________
  35. //  __ Typedefs_______________________________________________________________________
  36. //  __ Static Protos__________________________________________________________________
  37. static void ToolBoxInit(void);
  38. static Boolean OpenMainWindow( void );
  39. static void ShowHSVCircle2( void );
  40. static void WaitForQuit( void );
  41. static void GetAppName(char *pascalName);
  42.  
  43. //  __ Extern Globals_________________________________________________________________
  44. //  __ Static Globals_________________________________________________________________
  45. static OSErr                        gErr;
  46. static WindowPtr                gMainWindow;
  47. static Str32                        gAppName;
  48.  
  49. //  __ Functions______________________________________________________________________
  50.  
  51.  
  52.  
  53.  
  54.  
  55. //____ main __________________________________________________________________________
  56. //
  57. void main( void )
  58. {
  59.  
  60.     ToolBoxInit();
  61.     
  62.     if (!EnviroCheck())
  63.         ExitToShell();
  64.     
  65.     GetAppName((char *)gAppName);
  66.  
  67.     if (!OpenMainWindow())
  68.         ExitToShell();
  69.     
  70.     ShowHSVCircle2();
  71.     
  72.     WaitForQuit();
  73.     
  74.     if(NULL != gMainWindow)
  75.         DisposeWindow(gMainWindow);
  76.             
  77. }//main
  78.  
  79.  
  80. //____ ToolBoxInit __________________________________________________________________________
  81. //
  82. //    Basic initialization.
  83. //
  84. static void ToolBoxInit( void )
  85. {    
  86.     InitGraf(&qd.thePort);
  87.     InitFonts();
  88.     InitWindows();
  89.     InitMenus();
  90.     TEInit();
  91.     InitDialogs(NULL);
  92.     InitCursor();
  93.     FlushEvents(everyEvent, 0);
  94. }    //ToolBoxInit
  95.  
  96.  
  97. //____ OpenMainWindow __________________________________________________________________________
  98. //
  99. //    Create CLUT from scratch, filling it with customized colors suitable for our
  100. //    nefarious HSV circle-drawing needs. Open a window
  101. //
  102. //    Open our window, install palette built from a resource CTable.
  103. //    provided by the System.
  104. //
  105. //    All entries in palette marked pmTolerant, with a tolerance of 0x5000.
  106. //
  107. static Boolean OpenMainWindow( void )
  108. {
  109. PaletteHandle appPalette;                // the palette that we will make the window's palette
  110. CTabHandle            tempColorTable;
  111. HSVColor    ourHSV;
  112. RGBColor    resultingRGB;
  113. ColorSpecPtr    aClrSpec;
  114. short        x;
  115.  
  116.     ourHSV.hue = 0;
  117.     ourHSV.saturation = 65535;
  118.     ourHSV.value = 65535;
  119.  
  120.     //create a CLUT in memory
  121.     tempColorTable = (CTabHandle)NewHandle(sizeof(ColorTable) + (256 * sizeof(ColorSpec)));
  122.     (**tempColorTable).ctSeed = GetCTSeed();
  123.     (**tempColorTable).ctFlags = 0x0;
  124.     (**tempColorTable).ctSize = 255;
  125.     aClrSpec = (**tempColorTable).ctTable;
  126.  
  127.     //make a neutral gray for the background
  128.     resultingRGB.red = resultingRGB.blue = resultingRGB.green = 32768;
  129.     aClrSpec->rgb = resultingRGB;
  130.     aClrSpec++;
  131.     
  132.     //create a rainbow of colors and stuff them into consecutive rgbs in the CLUT.
  133.     for (x = 2; x < 255; x++)
  134.     {
  135.             ourHSV.hue += 65535 / 254;
  136.             HSV2RGB(&ourHSV,&resultingRGB);
  137.             aClrSpec->rgb = resultingRGB;
  138.             aClrSpec++;
  139.     }
  140.     
  141.  
  142.     // create and show the window, make sure it's frontmost
  143.     gMainWindow = GetNewCWindow( kMainWindowResID, ( Ptr )NULL, ( WindowPtr ) -1 );    
  144.     if (NULL == gMainWindow)            //real apps should handle this gracefully
  145.         return FALSE;
  146.     SetWTitle(gMainWindow,gAppName);
  147.     ShowWindow( gMainWindow );
  148.     SetPort( gMainWindow );
  149.  
  150.     //create a new Palette for our window, passing in tempColorTable and all
  151.     //of its bright, shiny colors
  152.     appPalette = NewPalette( 256, tempColorTable, pmTolerant, 0x0000 );
  153.     
  154.     //pop the new Palette into the window
  155.     NSetPalette( gMainWindow, appPalette, pmAllUpdates );
  156.     
  157.     //tell the hardware that the color for our window's changed and
  158.     //to make sure the colors our Palette is requesting are available.
  159.     ActivatePalette(gMainWindow);
  160.     
  161.     //release memory occupied by our temporary ColorTable.
  162.     DisposeCTable(tempColorTable);
  163.     
  164.     return TRUE;
  165. }//OpenWindowWithCTableID
  166.  
  167.  
  168. //____ ShowHSVCircle2 __________________________________________________________________________
  169. //
  170. //    This is similar to the HSV Demo 1 function:
  171. //
  172. //        Walk incrementally around the perimeter of the HSV color wheel, creating HSV colors
  173. //        on each step, translating them to RGB, and then drawing a dot with that color
  174. //        on a circle corresponding the color's origin on the HSV wheel.
  175. //
  176. //        Changing the value of kNumCircles to a number greater than one will cause more HSV
  177. //        circles to be drawn, each of which will exhibit increasing Saturation and Value.
  178. //
  179. //    However, since we've craftily installed a Palette with the colors we know we'll need,
  180. //    the image rendered is much nicer.
  181. //
  182. //    Also, note that the string drawn looks nifty as it cycles from color to color. It does,
  183. //    however, have to be drawn every time. Keep this in mind when we explore Palette Animation.
  184. //
  185. static void ShowHSVCircle2( void )
  186. {
  187. #define        kNumSteps                    256                                                //defines how many dots
  188. #define        mThetaStepSize         (6.283 / kNumSteps)                //how far around our circle to go
  189. #define        mColorStepSize        (65535 / kNumSteps)                //how far to go around color wheel per dot
  190. #define        kNumCircles                1                                                    // <=== try changing this to values like 5 or 10
  191. #define        kRadius                        120                                                //max radius of our circle
  192. #define        mRadiusStep                (kRadius / kNumCircles)        //how much to enlarge each circle
  193. #define        mSatValStep                (65535 / kNumCircles)            //amount to increments saturation and value
  194. #define        kHalfRectSize            20                                                //halve length to make centering easy
  195.  
  196. short        step;
  197. short        x, y, cenX, cenY;
  198. double    theta;
  199. Rect        aRect;
  200. short        theRadius;
  201. short        circleNum;
  202. HSVColor    ourHSV;
  203. RGBColor    resultingRGB;
  204.  
  205.     TextFont(0);    //use Chicago
  206.     TextSize(12);
  207.     
  208.     cenX = qd.thePort->portRect.right / 2;
  209.     cenY = qd.thePort->portRect.bottom / 2;
  210.     
  211.     //use a neutral gray for the background
  212.     resultingRGB.red = resultingRGB.blue = resultingRGB.green = 32768;
  213.     RGBForeColor(&resultingRGB);
  214.     PaintRect(&qd.thePort->portRect);
  215.     
  216.     //start out with full red
  217.     ourHSV.hue = 0;
  218.     ourHSV.saturation = 0;
  219.     ourHSV.value = 0;
  220.     theRadius = 0;
  221.     for (circleNum = 0; circleNum < kNumCircles; circleNum++)
  222.     {        
  223.         theRadius += mRadiusStep; 
  224.         ourHSV.saturation += mSatValStep;
  225.         ourHSV.value += mSatValStep;
  226.  
  227.         //draw HSV circle
  228.         for (step = 0, theta = 0.0; step < kNumSteps; step++)
  229.         {
  230.             MoveTo(20,20);
  231.             DrawString(gAppName);
  232.             theta += mThetaStepSize;
  233.             x = cenX + theRadius * cos(theta);
  234.             y = cenY - theRadius * sin(theta);
  235.     
  236.             ourHSV.hue += mColorStepSize;                //move clockwise along color wheel
  237.             HSV2RGB(&ourHSV,&resultingRGB);
  238.     
  239.             RGBForeColor(&resultingRGB);
  240.             
  241.             SetRect(&aRect, x - kHalfRectSize, y - kHalfRectSize, x + kHalfRectSize, y + kHalfRectSize);
  242.             PaintOval(&aRect);
  243.         }
  244.  
  245.     }//for circleNum
  246. }//ShowHSVCircle2
  247.  
  248.  
  249. //____ WaitForQuit __________________________________________________________________________
  250. //
  251. //    Hangs out until there is any keyboard or mouse activity. A rather plain instance of
  252. //    an event loop; a real program would be more robust.
  253. //
  254. static void WaitForQuit( void )
  255. {
  256. Boolean    wait;
  257. EventRecord        theEvent;
  258.     
  259.     wait = TRUE;
  260.     while (wait)
  261.     {
  262.         if(WaitNextEvent(everyEvent, &theEvent, kSleepTicks, 0L))
  263.         {
  264.             switch (theEvent.what)
  265.             {
  266.                 case mouseDown:
  267.                 case keyDown:
  268.                     wait = FALSE;
  269.                 break;
  270.             }//switch (theEvent.what)
  271.         }//if WaitNextEvent
  272.     }//while
  273.  
  274. }//WaitForQuit
  275.  
  276.  
  277. //____ GetAppName __________________________________________________________________________
  278. //
  279. //    This happy function does just what it says. But, instead of using some scary (and
  280. //    soon-to-be obsolete) low memory global to get at the application's name, we use
  281. //    the Process Manager, even if it does force us through a couple of non-intuitive
  282. //    hoops in the, uh, process...
  283. //
  284. static void GetAppName(char *pascalName)
  285. {
  286. ProcessSerialNumber        PSN;
  287. ProcessInfoRec            info;
  288.  
  289. gErr = GetCurrentProcess(&PSN);
  290. if (noErr != gErr)
  291.     goto Xit;
  292.  
  293. //stick stuff into info rec before calling GetProcessInformation
  294. info.processInfoLength = sizeof( ProcessInfoRec );
  295. info.processAppSpec = nil;
  296. info.processName = ( StringPtr ) pascalName;
  297.  
  298. gErr = GetProcessInformation(&PSN,&info);
  299. if (noErr != gErr)
  300.     goto Xit;
  301.  
  302. Xit:
  303. if (noErr != gErr)    //was there an error?
  304. {
  305.     BlockMove("\8Untitled", pascalName, 9);
  306. }
  307.  
  308. return;
  309.  
  310. }//GetAppName
  311.